#ifndef __DAP_CONFIG_H__
#define __DAP_CONFIG_H__

#include "IO_Config.h"

#define CPU_CLOCK               SystemCoreClock

#define IO_PORT_WRITE_CYCLES    2U

#define DAP_SWD                 1
#define DAP_JTAG                1
#define DAP_JTAG_DEV_CNT        4
#define DAP_DEFAULT_PORT        2       /*1:SWD,2:JTAG*/
#define DAP_DEFAULT_SWJ_CLOCK   1000000U
#define DAP_PACKET_SIZE         64
#define DAP_PACKET_COUNT        4U
#define SWO_UART                0
#define SWO_UART_DRIVER         0
#define SWO_UART_MAX_BAUDRATE   10000000U
#define SWO_MANCHESTER          0
#define SWO_BUFFER_SIZE         4096
#define SWO_STREAM              0
#define TIMESTAMP_CLOCK         1000000U
#define DAP_UART                0
#define DAP_UART_DRIVER         1
#define DAP_UART_RX_BUFFER_SIZE 1024U
#define DAP_UART_TX_BUFFER_SIZE 1024U
#define DAP_UART_USB_COM_PORT   1
#define TARGET_FIXED            0

extern int SystemCoreClock;
static void _set_gpio_out(gpio_type*gpio,uint32_t pin_bit);
static void _set_gpio_in(gpio_type*gpio,uint32_t  pin_bit);
static void _set_gpio_od(gpio_type*gpio,uint32_t  pin_bit);

#define _PIN_SET_VAL(name,val)  name##_PIN_PORT->scr = (name##_PIN)<<((val)?0:16)
#define _PIN_SET(name) name##_PIN_PORT->scr = (name##_PIN)
#define _PIN_CLR(name) name##_PIN_PORT->scr = (name##_PIN)<<16
#define _PIN_VAL(name) (name##_PIN_PORT->idt >> name##_PIN_Bit) & 1

__STATIC_INLINE void PORT_JTAG_SETUP(void)
{
    _set_gpio_out(JTAG_TCK_PIN_PORT,JTAG_TCK_PIN_Bit);
    _set_gpio_out(JTAG_OUT_PIN_PORT,JTAG_OUT_PIN_Bit);
    _set_gpio_out(JTAG_TMS_PIN_PORT,JTAG_TMS_PIN_Bit);
    _set_gpio_out(JTAG_TRST_PIN_PORT,JTAG_TRST_PIN_Bit);
    _set_gpio_in (JTAG_IN_PIN_PORT ,JTAG_IN_PIN_Bit);
    _PIN_SET_VAL(JTAG_TRST,0);
}

__STATIC_INLINE void PORT_SWD_SETUP(void)
{
    _set_gpio_out(SWD_CLK_PIN_PORT,SWD_CLK_PIN_Bit);
    _set_gpio_out(SWD_DIO_PIN_PORT,SWD_DIO_PIN_Bit);
}

__STATIC_INLINE void PORT_OFF(void)
{
    //暂时不处理
}

__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void)
{
    return _PIN_VAL(JTAG_TCK);
}

__STATIC_FORCEINLINE void     PIN_SWCLK_TCK_SET(void)
{
    _PIN_SET(JTAG_TCK);
}

__STATIC_FORCEINLINE void     PIN_SWCLK_TCK_CLR(void)
{
    _PIN_CLR(JTAG_TCK);
}

__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void)
{
    return _PIN_VAL(JTAG_TMS);
}

__STATIC_FORCEINLINE void     PIN_SWDIO_TMS_SET(void)
{
    _PIN_SET(JTAG_TMS);
}

__STATIC_FORCEINLINE void     PIN_SWDIO_TMS_CLR(void)
{
    _PIN_CLR(JTAG_TMS);
}

__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void)
{
    _set_gpio_out(SWD_DIO_PIN_PORT,SWD_DIO_PIN_Bit);
    _PIN_SET(SWD_DIO);
}

__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void)
{
    _set_gpio_in(SWD_DIO_PIN_PORT,SWD_DIO_PIN_Bit);
    _PIN_SET(SWD_DIO);
}

__STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void)
{
   return (JTAG_OUT_PIN_PORT->odt >> JTAG_OUT_PIN_Bit) & 1;
}

__STATIC_FORCEINLINE void     PIN_TDI_OUT(uint32_t bit)
{
    _PIN_SET_VAL(JTAG_OUT,bit&1);
}

__STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void)
{
    return _PIN_VAL(JTAG_IN);
}

__STATIC_FORCEINLINE void     PIN_nTRST_OUT(uint32_t bit)
{
    _PIN_SET_VAL(JTAG_TRST,bit&1);
}

__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void)
{
    return (nRESET_PIN_PORT->idt >> nRESET_PIN_Bit) & 1;
}

__STATIC_FORCEINLINE void     PIN_nRESET_OUT(uint32_t bit)
{
    // Only drive RESET low, otherwise let the target pull it high.
    if (bit) {
        // Change pin to input.
        // GPIO->DIRCLR[PIN_PIO_PORT] = PIN_RESET_MASK;
        // // Disable level translator output.
        // GPIO->B[PIN_PIO_PORT][PIN_RESET_TXEN] = 0;
        // // Set RESET to high. (Probably not be necessary)
        // GPIO->B[PIN_PIO_PORT][PIN_RESET] = 1;

        //设置上拉
        _set_gpio_in(nRESET_PIN_PORT,nRESET_PIN_Bit);
        _PIN_SET(nRESET);
    }
    else {
        // // Set RESET low.
        // GPIO->B[PIN_PIO_PORT][PIN_RESET] = 0;
        // // Enable level translator output to drive.
        // GPIO->B[PIN_PIO_PORT][PIN_RESET_TXEN] = 1;
        // // Change pin to output.
        // GPIO->DIRSET[PIN_PIO_PORT] = PIN_RESET_MASK;

        //设置低电平输出
        _set_gpio_out(nRESET_PIN_PORT,nRESET_PIN_Bit);
        _PIN_CLR(nRESET);
    }
}

__STATIC_INLINE void LED_CONNECTED_OUT(uint32_t bit)
{
}

__STATIC_INLINE void LED_RUNNING_OUT(uint32_t bit)
{
}

__STATIC_INLINE uint32_t TIMESTAMP_GET (void) {
  return TMR3->cval / (CPU_CLOCK / TIMESTAMP_CLOCK);
}

__STATIC_INLINE void DAP_SETUP(void)
{
    crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);

    _set_gpio_out(JTAG_TCK_PIN_PORT,JTAG_TCK_PIN_Bit);
    _set_gpio_out(JTAG_OUT_PIN_PORT,JTAG_OUT_PIN_Bit);

    _set_gpio_in (JTAG_IN_PIN_PORT,JTAG_IN_PIN_Bit);
    _set_gpio_od (nRESET_PIN_PORT,nRESET_PIN_Bit);

    tmr_counter_enable(TMR3,TRUE);

    _PIN_SET(JTAG_TCK);
    _PIN_SET(JTAG_OUT);
    _PIN_SET(nRESET);

    //LED设置
}

__STATIC_INLINE uint32_t RESET_TARGET(void)
{
    return (0);              // change to '1' when a device reset sequence is implemented
}

__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void)
{
    return (0);   // Not available
}

__STATIC_FORCEINLINE void     PIN_SWDIO_OUT(uint32_t bit)
{
    if (bit & 1) {
        _PIN_SET(SWD_DIO);
    } else {
        _PIN_CLR(SWD_DIO);
    }
}

__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void)
{
    return _PIN_VAL(SWD_DIO);
}

#endif

